<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.8.0 -->
<title>0099: SFX - Button Interactions | gtkDcoding</title>
<meta name="generator" content="Jekyll v4.3.4" />
<meta property="og:title" content="0099: SFX - Button Interactions" />
<meta name="author" content="Ron Tarrant" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="This GTK Tutorial covers interactions between buttons." />
<meta property="og:description" content="This GTK Tutorial covers interactions between buttons." />
<link rel="canonical" href="http://localhost:4000/posts/0099-sfx-button-interactions-i-text-labels.html" />
<meta property="og:url" content="http://localhost:4000/posts/0099-sfx-button-interactions-i-text-labels.html" />
<meta property="og:site_name" content="gtkDcoding" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2020-01-21T00:00:00-05:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="0099: SFX - Button Interactions" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Ron Tarrant"},"dateModified":"2020-01-21T00:00:00-05:00","datePublished":"2020-01-21T00:00:00-05:00","description":"This GTK Tutorial covers interactions between buttons.","headline":"0099: SFX - Button Interactions","mainEntityOfPage":{"@type":"WebPage","@id":"http://localhost:4000/posts/0099-sfx-button-interactions-i-text-labels.html"},"url":"http://localhost:4000/posts/0099-sfx-button-interactions-i-text-labels.html"}</script>
<!-- End Jekyll SEO tag -->
<link rel="stylesheet" href="../assets/main.css">
  <link rel="stylesheet" href="../css/style.css" /><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="gtkDcoding" /></head>
<body><header class="site-header" role="banner">

  <div class="wrapper"><a class="site-title" rel="author" href="../">gtkDcoding</a><nav class="site-nav">
        <input type="checkbox" id="nav-trigger" class="nav-trigger" />
        <label for="nav-trigger">
          <span class="menu-icon">
            <svg viewBox="0 0 18 15" width="18px" height="15px">
              <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
            </svg>
          </span>
        </label>

        <div class="trigger"><a class="page-link" href="../about.html">About</a><a class="page-link" href="../index-reverse.html">Posts in Date Order</a><a class="page-link" href="../topics.html">Blog Posts by Topic</a></div>
      </nav></div>
</header>
<main class="page-content" aria-label="Content">
      <div class="wrapper">
        <article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
	<header class="post-header">
		<link rel="stylesheet" href="../css/font_size.css" />
		<link rel="stylesheet" href="../css/figure.css" />
		<link rel="stylesheet" href="../css/topics/sfx.css" />  <!-- sub in the tag/topic -->
		<link rel="stylesheet" href="../css/modal.css" />
		<link rel="stylesheet" href="../css/post.css" />
		<link rel="stylesheet" href="../css/mascot_effects.css" />

		
		
		<p class="post-meta">
		<time class="dt-published" datetime="2020-01-21T00:00:00-05:00" itemprop="datePublished">Tuesday, January 21, 2020
		</time>• by <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span class="p-author h-card" itemprop="name">Ron Tarrant</span></span></p>
	</header>

	<div class="post-content e-content" itemprop="articleBody">
		<div class="skew-line"></div>
		<h1 id="0099-sfx---button-interactions">0099: SFX - Button Interactions</h1>

<p>This post came about as the result of a request from Joel Christensen who asked me to cook up a demo wherein clicking one <em>GTK</em> <code class="language-plaintext highlighter-rouge">Button</code> would change the appearance of another.</p>

<p>Anyway, on with the show…</p>

<h2 id="changing-another-buttons-text-label">Changing Another Button’s Text Label</h2>

<!-- 0, 1 -->
<!-- first occurrence of application and terminal screen shots on a single page -->
<div class="screenshot-frame">
	<div class="frame-header">
		Results of this example:
	</div>
	<div class="frame-screenshot">
		<figure>
			<img id="img0" src="../images/screenshots/016_sfx/sfx_01.png" alt="Current example output" />		<!-- img# -->
			
			<!-- Modal for screenshot -->
			<div id="modal0" class="modal">																	<!-- modal# -->
				<span class="close0">&times;</span>															<!-- close# -->
				<img class="modal-content" id="img00" />															<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal0");														// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img0");															// img#
			var modalImg = document.getElementById("img00");													// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close0")[0];											// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>
			<figcaption>
			Current example output
			</figcaption>
		</figure>
	</div>

	<div class="frame-terminal">
		<figure class="right">
			<img id="img1" src="../images/screenshots/016_sfx/sfx_01_term.png" alt="Current example terminal output" />		<!-- img#, filename -->

			<!-- Modal for terminal shot -->
			<div id="modal1" class="modal">																				<!-- modal# -->
				<span class="close1">&times;</span>																		<!-- close# -->
				<img class="modal-content" id="img11" />																		<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal1");																	// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img1");																		// img#
			var modalImg = document.getElementById("img11");																// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close1")[0];														// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>

			<figcaption>
				Current example terminal output (click for enlarged view)
			</figcaption>
		</figure>
	</div>

	<div class="frame-footer">																								<!-- ------------- filename (below) --------- -->
		The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/016_sfx/sfx_01_button_to_button_text.d" target="_blank">here</a>.
	</div>
</div>
<!-- end of snippet for first (1st) occurrence of application and terminal screen shots on a single page -->

<p>But let’s get both buttons to react, each to the other. This isn’t really an <em>Observer</em> pattern, although it could be written as one. Instead, you might think of it as a <em>Cooperator</em> pattern if, indeed, it warrants being called a pattern at all. (<em>Note: in an upcoming post, we’ll look at using the</em> Observer <em>pattern to get a Button to affect changes in whatever types of <code class="language-plaintext highlighter-rouge">Widget</code> we point it at.</em>)</p>

<p>For this demonstration, the most straightforward (and immediately noticeable) change that can be made in the partner <code class="language-plaintext highlighter-rouge">Button</code> is to switch out the text label, so that’s what we’ll do.</p>

<p>And since the text label changes will go back and forth between the two <code class="language-plaintext highlighter-rouge">Button</code>s, let’s call this class <code class="language-plaintext highlighter-rouge">PingPongButton</code>.</p>

<h3 id="the-pingpongbutton-preamble">The PingPongButton Preamble</h3>

<p>Here’s what gets declared and defined in the preamble:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">labelNumber</span> <span class="p">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nb">string</span> <span class="n">labelText</span><span class="p">;</span>
<span class="nb">string</span><span class="p">[]</span> <span class="n">nameSuffixes</span> <span class="p">=</span> <span class="p">[</span><span class="s">" Tra"</span><span class="p">,</span> <span class="s">" La"</span><span class="p">,</span> <span class="s">" Li"</span><span class="p">];</span>
<span class="n">PingPongButton</span> <span class="n">partnerButton</span><span class="p">;</span>
</code></pre></div></div>

<p>And here’s what they mean:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">int labelNumber</code>: an index into the <code class="language-plaintext highlighter-rouge">nameSuffixes</code> array,</li>
  <li><code class="language-plaintext highlighter-rouge">string labelText</code>: the base name for the button (which is passed in from outside),</li>
  <li><code class="language-plaintext highlighter-rouge">string nameSuffixes</code>: an array of suffixes for the button names that we can switch between each time a <code class="language-plaintext highlighter-rouge">PingPongButton</code> is clicked, and</li>
  <li><code class="language-plaintext highlighter-rouge">PingPongButton partnerButton</code>: a reference to a companion button that will interact with this one.</li>
</ul>

<h3 id="the-pingpongbutton-constructor">The PingPongButton Constructor</h3>

<p>This is fairly plain and simple despite the extra functionality we’re stuffing into it:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">this</span><span class="p">(</span><span class="nb">string</span> <span class="n">buttonLabel</span><span class="p">)</span>
<span class="p">{</span>
	<span class="k">super</span><span class="p">(</span><span class="n">buttonLabel</span> <span class="p">~</span> <span class="n">nameSuffixes</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
	<span class="n">labelText</span> <span class="p">=</span> <span class="n">buttonLabel</span><span class="p">;</span>
		
	<span class="n">addOnButtonPress</span><span class="p">(&amp;</span><span class="n">onButtonPress</span><span class="p">);</span>
		
<span class="p">}</span> <span class="c1">// this()</span>
</code></pre></div></div>

<p>As mentioned above, we’re passing in a string to use as <code class="language-plaintext highlighter-rouge">Button</code> label text. That gets concatenated to the first element of the <code class="language-plaintext highlighter-rouge">nameSuffixes</code> array on start-up, but we’ll be switching that up in a moment.</p>

<p>And, of course, the only other thing happening here is hooking up the <code class="language-plaintext highlighter-rouge">onButtonPress</code> signal.</p>

<p>Moving right along…</p>

<h3 id="the-callback">The Callback</h3>

<p>There’s nothing mysterious here:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="n">onButtonPress</span><span class="p">(</span><span class="n">Event</span> <span class="n">e</span><span class="p">,</span> <span class="n">Widget</span> <span class="n">w</span><span class="p">)</span>
<span class="p">{</span>
	<span class="nb">string</span> <span class="n">newLabel</span><span class="p">;</span>
	
	<span class="n">labelNumber</span><span class="p">++;</span>
		
	<span class="k">if</span><span class="p">(</span><span class="n">labelNumber</span> <span class="p">==</span> <span class="n">nameSuffixes</span><span class="p">.</span><span class="n">length</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">labelNumber</span> <span class="p">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="p">}</span>
		
	<span class="n">newLabel</span> <span class="p">=</span> <span class="n">labelText</span> <span class="p">~</span> <span class="n">nameSuffixes</span><span class="p">[</span><span class="n">labelNumber</span><span class="p">];</span>
	<span class="n">partnerButton</span><span class="p">.</span><span class="n">setLabel</span><span class="p">(</span><span class="n">newLabel</span><span class="p">);</span>
		
	<span class="n">writeln</span><span class="p">(</span><span class="s">"Partner button label has changed to: "</span><span class="p">,</span> <span class="n">newLabel</span><span class="p">);</span>
		
	<span class="k">return</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
		
<span class="p">}</span> <span class="c1">// onButtonPress()</span>
</code></pre></div></div>

<p>After setting up a string to hold the new label text we’re about to build, we increment the index we use for digging into the <code class="language-plaintext highlighter-rouge">nameSuffixes</code> array.</p>

<p>Then we check to make sure we aren’t running off the end of the <code class="language-plaintext highlighter-rouge">nameSuffixes</code> string array by testing for the array length and rewinding our index to <code class="language-plaintext highlighter-rouge">0</code>.</p>

<p>From there, it’s all rather predictable. We concatenate the new label text together and slap it onto the companion button.</p>

<p>But we haven’t mentioned how to get the reference to the companion <code class="language-plaintext highlighter-rouge">Button</code>. Well, like most things <em>GtkD</em>, it’s not complicated once you’ve seen it done…</p>

<h3 id="the-addpartner-function">The addPartner() Function</h3>

<p>Here’s the last piece of the puzzle:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">addPartner</span><span class="p">(</span><span class="n">PingPongButton</span> <span class="n">newPartnerButton</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">writeln</span><span class="p">(</span><span class="s">"New partner button for "</span><span class="p">,</span> <span class="n">getLabel</span><span class="p">(),</span> <span class="s">": "</span><span class="p">,</span> <span class="n">newPartnerButton</span><span class="p">.</span><span class="n">getLabel</span><span class="p">());</span>
	<span class="n">partnerButton</span> <span class="p">=</span> <span class="n">newPartnerButton</span><span class="p">;</span>
		
<span class="p">}</span> <span class="c1">// addPartner()</span>
</code></pre></div></div>

<p>This function is called from the <code class="language-plaintext highlighter-rouge">AppBox</code> class right after both <code class="language-plaintext highlighter-rouge">PingPongButton</code>s are instantiated. One call for each <code class="language-plaintext highlighter-rouge">PingPongButton</code> and we’re all set up.</p>

<p>And since we’re talking about it, here’s…</p>

<h3 id="the-appbox-class">The AppBox Class</h3>

<p>Let’s just look at the whole thing, shall we?</p>

<h4 id="preamble">Preamble</h4>

<p>Meet <code class="language-plaintext highlighter-rouge">Ralph</code> and <code class="language-plaintext highlighter-rouge">George</code>, our two <code class="language-plaintext highlighter-rouge">Button</code>s, each with the power to change the other:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">string</span> <span class="n">ralph</span> <span class="p">=</span> <span class="s">"Ralph"</span><span class="p">,</span> <span class="n">george</span> <span class="p">=</span> <span class="s">"George"</span><span class="p">;</span>
<span class="n">PingPongButton</span> <span class="n">pingButton</span><span class="p">,</span> <span class="n">pongButton</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">globalPadding</span> <span class="p">=</span> <span class="mi">10</span><span class="p">,</span> <span class="n">localPadding</span> <span class="p">=</span> <span class="mi">5</span><span class="p">;</span>
</code></pre></div></div>

<h4 id="constructor">Constructor</h4>

<p>And here is how we set them up:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">this</span><span class="p">()</span>
<span class="p">{</span>
	<span class="k">super</span><span class="p">(</span><span class="n">Orientation</span><span class="p">.</span><span class="n">HORIZONTAL</span><span class="p">,</span> <span class="n">globalPadding</span><span class="p">);</span>
		
	<span class="n">pingButton</span> <span class="p">=</span> <span class="k">new</span> <span class="n">PingPongButton</span><span class="p">(</span><span class="n">ralph</span><span class="p">);</span>
	<span class="n">packStart</span><span class="p">(</span><span class="n">pingButton</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="n">localPadding</span><span class="p">);</span>

	<span class="n">pongButton</span> <span class="p">=</span> <span class="k">new</span> <span class="n">PingPongButton</span><span class="p">(</span><span class="n">george</span><span class="p">);</span>
	<span class="n">packStart</span><span class="p">(</span><span class="n">pongButton</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="n">localPadding</span><span class="p">);</span>

	<span class="c1">// partner up the buttons</span>
	<span class="n">pingButton</span><span class="p">.</span><span class="n">addPartner</span><span class="p">(</span><span class="n">pongButton</span><span class="p">);</span>
	<span class="n">pongButton</span><span class="p">.</span><span class="n">addPartner</span><span class="p">(</span><span class="n">pingButton</span><span class="p">);</span>
		
<span class="p">}</span> <span class="c1">// this()</span>
</code></pre></div></div>

<p>The most important bit here is that both buttons need to be instantiated before we make the calls to <code class="language-plaintext highlighter-rouge">addPartner()</code>, one call for each button. Obviously, <code class="language-plaintext highlighter-rouge">addPartner()</code> can only be called at a time when both buttons exist.</p>

<h2 id="conclusion">Conclusion</h2>

<p>And that’s how to affect the appearance of one <code class="language-plaintext highlighter-rouge">Button</code> with another. But we’re not done with this because it occurred to me that we might also want to change other things besides the text labels. What about the color of the <code class="language-plaintext highlighter-rouge">Button</code>? Or the text label’s font?</p>

<p>Tune in next time when we’ll take a look at this. Here’s a hint: it involves <em>CSS</em>.</p>

<p>See you then.</p>

<div class="blog-nav">
	<div style="float: left;">
		<a href="./0098-headerbar-more.html">Previous: HeaderBar - More</a>
	</div>
<!--
	<div style="float: right;">
		<a href="./0100-sfx-button-interactions-ii-color-font-shape.html">Next: Button Interactions II</a>
	</div>
-->
</div>
<p>
	<h3></h3>
<div class="inpage-frame">
	<a href="https://github.com/sponsors/rontarrant">
		<BR>
		<BR>
		<B>Is this article useful? Educational? Entertaining, perhaps?</B>
		<BR>
		<figure class="left">
			<img src="../images/favorite_32.png" alt="Sponsorship heart" style="width: 32px; height: 32px;">
		</figure>
		You're free to accept or decline this invitation to become our newest sponsor.
	</a>
</div>
	<h4 class="comment-blurb"><B>Comments? Questions? Observations?</B></h4>
	<p>
		Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.
	</p>
	<script src="https://utteranc.es/client.js"
		repo="rontarrant"
		issue-term="pathname"
		theme="github-light"
		crossorigin="anonymous"
		async>
	</script>
	<ul>
		<li> come on over to the <a href="https://forum.dlang.org/">D Language Forum</a> and look for one of the <i>gtkDcoding</i> announcement posts, </li>
		<li> drop by <a href="https://forum.gtkd.org/">the <i>GtkD Forum</i></a>,</li>
		<li> follow the link below to email me, or</li>
		<li> go to the	<a href="https://www.facebook.com">gtkDcoding Facebook page.</a></li>
	</ul>
</p>
<p> You can also subscribe <a href="/feed.xml">via RSS</a> so you won't miss anything. Thank you very much for dropping by.</p>
<p>&copy; Copyright 2025 Ron Tarrant </p>
</div>

	<a class="u-url" href="./0099-sfx-button-interactions-i-text-labels.html" hidden></a>
</article>

      </div>
    </main><footer class="site-footer h-card">
  <data class="u-url" href="/"></data>

  <div class="wrapper">

    <h2 class="footer-heading">gtkDcoding</h2>

    <div class="footer-col-wrapper">
      <div class="footer-col footer-col-1">
        <ul class="contact-list">
          <li class="p-name">Ron Tarrant</li><li><a class="u-email" href="mailto:gtkDcoding@gmail.com">gtkDcoding@gmail.com</a></li></ul>
      </div>

      <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/rontarrant"><svg class="svg-icon"><use xlink:href="../assets/minima-social-icons.svg#github"></use></svg> <span class="username">rontarrant</span></a></li></ul>
</div>

      <div class="footer-col footer-col-3">
        <p>Simple examples of how to use GtkD to build GUI applications.</p>
      </div>
    </div>

  </div>

</footer>
</body>

</html>
